/* simple PWM LED driver */

/* Copyright (C) 2011 David Zanetti
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/* theory:
 * We use Timer1 to run a sysclk-derrived clock bounded by 10 bits.
 * 0x0000 -> 0x03ff (10 bit resolution)
 * The output at OCR1A (red LED), OCR1B (green), is toggled by
 * matches against those registers.
 * This runs in Fast PWM mode.
 */

#include <avr/io.h>
#include <stdio.h>
#include "global.h"
#include <util/delay.h>
#include "led.h"

/* set up the timers, and set brightnesses to 0 */
void led_init(void) {
	/* don't generate any interrupts for timer1 */
	TIMSK1 = 0;

	/* PWM mode, 10-bit fast PWM, clear on match, set on bottom */
	TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10) | (1 << WGM11);
	TCCR1B |= (1 << WGM12);

	/* the output compares don't matter right now, we'll set them
    in the brightness set code */

	/* run the clock, using a 1/256 prescale, off the io clock */
	TCCR1B |= (1 << CS10);

	/* make leds both output pins */
	DDRD |= (1 << PORTD5) | (1 << PORTD4);
	/* they won't actually be toggled unless their output compare is
    activated */
	PORTD &= ~(1 << PORTD5 & 1 << PORTD4);
}

/* set the red brightness */
void led_red(uint16_t brightness) {
	if (!brightness) {
		/* just disconnect the pin */
		TCCR1A &= ~(1 << COM1A1);
		return;
	}
	/* reconnect the output */
	TCCR1A |= (1 << COM1A1);
	/* set the brightness limit */
	OCR1A = brightness;
}

/* set the green brightness */
void led_green(uint16_t brightness) {
	if (!brightness) {
		/* just disconnect the pin */
		TCCR1A &= ~(1 << COM1B1);
		return;
	}
	TCCR1A |= (1 << COM1B1);
	/* set the brightness limit */
	OCR1B = brightness;
}


